#include "bsp_ili9341_yuanzi.h"

//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;
//LCD的画笔颜色和背景色	   
uint16_t POINT_COLOR = 0x0000;	//画笔颜色
uint16_t BACK_COLOR = 0xFFFF;  //背景色

//写寄存器函数
//data:寄存器值
static void lcd_wr_reg(uint16_t data)
{ 
    LCD_RS_CLR;//写地址  
    LCD_CS_CLR; 
    DATAOUT(data); 
    LCD_WR_CLR; 
    LCD_WR_SET; 
    LCD_CS_SET;   
}
//写数据函数
static void lcd_wr_data(uint16_t data)
{
    LCD_RS_SET;
    LCD_CS_CLR;
    DATAOUT(data);
    LCD_WR_CLR;
    LCD_WR_SET;
    LCD_CS_SET;
}

//读LCD数据
//返回值:读到的值
static uint16_t lcd_rd_data(void)
{										   
	uint16_t data;
 	GPIOB->CRL=0X88888888;          //PB0-7  上拉输入
	GPIOB->CRH=0X88888888;          //PB8-15 上拉输入
	GPIO_Write(GPIOB, 0x0000);      //全部输出0

	LCD_RS_SET;
	LCD_CS_CLR;
	LCD_RD_CLR;			   
	data = DATAIN;  
	LCD_RD_SET;
	LCD_CS_SET; 

	GPIOB->CRL=0X33333333;          //PB0-7  上拉输出
	GPIOB->CRH=0X33333333;          //PB8-15 上拉输出
	GPIO_Write(GPIOB, 0xffff);      //全部输出高
    
	return data;  
}

//写寄存器
//LCD_Reg:寄存器编号
//LCD_RegValue:要写入的值
static void lcd_write_reg(uint16_t lcd_reg, uint16_t lcd_reg_val)
{	
	lcd_wr_reg(lcd_reg);    
	lcd_wr_data(lcd_reg_val);
}

//读寄存器
//LCD_Reg:寄存器编号
//返回值:读到的值
static uint16_t lcd_read_reg(uint16_t lcd_reg)
{										   
 	lcd_wr_reg(lcd_reg);  //写入要读的寄存器号  
	return lcd_rd_data(); 
} 

static void lcd_display_dir(uint8_t dir)
{
	if(dir==0)			
	{
		lcddev.dir=0;	
		lcddev.width=240;
		lcddev.height=320;
        lcddev.wramcmd=0X2C;
	 	lcddev.setxcmd=0X2A;
		lcddev.setycmd=0X2B;
    } 
    else
    {
        lcddev.dir=1;	    
        lcddev.width=320;
        lcddev.height=240;
        lcddev.wramcmd=0X2C;
        lcddev.setxcmd=0X2A;
        lcddev.setycmd=0X2B;  
    }        
    
}

void bsp_ili9341_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能PORTB,C时钟和AFIO时钟
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//开启SWD，失能JTAG
    
    /*
    **  PC6 :LCD_RD
    **  PC7 :LCD_WR
    **  PC8 :LCD_RS
    **  PC9 :LCD_CS
    **  PC10:LCD_BL
    */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6;	   /// PORTC6~10复用推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
    
    /*
    ** PB0-15:LCDDATA0-15
    */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;	                                                // PORTB推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);                                                      // GPIOB
    GPIO_SetBits(GPIOB,GPIO_Pin_All);
    
    delay_ms(50);
    lcd_write_reg(0x0000, 0x0001);
    delay_ms(50);
    lcddev.id = lcd_read_reg(0x0000);
    
    lcd_wr_reg(0XD3);				   
    lcd_rd_data(); 				 
    lcd_rd_data();   	    	 
    lcddev.id = lcd_rd_data();   	 				   
    lcddev.id <<= 8;
    lcddev.id |= lcd_rd_data();

    printf(" LCD ID:%x\r\n",lcddev.id);                                                        //打印LCD ID  

    if(lcddev.id == 0x9341)
    {
        lcd_wr_reg(0xCF);  
        lcd_wr_data(0x00); 
        lcd_wr_data(0xC1); 
        lcd_wr_data(0X30); 
        lcd_wr_reg(0xED);   
        lcd_wr_data(0x64); 
        lcd_wr_data(0x03); 
        lcd_wr_data(0X12); 
        lcd_wr_data(0X81); 
        lcd_wr_reg(0xE8);  
        lcd_wr_data(0x85); 
        lcd_wr_data(0x10); 
        lcd_wr_data(0x7A); 
        lcd_wr_reg(0xCB);  
        lcd_wr_data(0x39); 
        lcd_wr_data(0x2C); 
        lcd_wr_data(0x00); 
        lcd_wr_data(0x34); 
        lcd_wr_data(0x02); 
        lcd_wr_reg(0xF7);  
        lcd_wr_data(0x20); 
        lcd_wr_reg(0xEA);  
        lcd_wr_data(0x00); 
        lcd_wr_data(0x00); 
        lcd_wr_reg(0xC0);    //Power control 
        lcd_wr_data(0x1B);   //VRH[5:0] 
        lcd_wr_reg(0xC1);    //Power control 
        lcd_wr_data(0x01);   //SAP[2:0];BT[3:0] 
        lcd_wr_reg(0xC5);    //VCM control 
        lcd_wr_data(0x30); 	 //3F
        lcd_wr_data(0x30); 	 //3C
        lcd_wr_reg(0xC7);    //VCM control2 
        lcd_wr_data(0XB7); 
        lcd_wr_reg(0x36);    // Memory Access Control 
        lcd_wr_data(0x48); 
        lcd_wr_reg(0x3A);   
        lcd_wr_data(0x55); 
        lcd_wr_reg(0xB1);   
        lcd_wr_data(0x00);   
        lcd_wr_data(0x1A); 
        lcd_wr_reg(0xB6);    // Display Function Control 
        lcd_wr_data(0x0A); 
        lcd_wr_data(0xA2); 
        lcd_wr_reg(0xF2);    // 3Gamma Function Disable 
        lcd_wr_data(0x00); 
        lcd_wr_reg(0x26);    //Gamma curve selected 
        lcd_wr_data(0x01); 
        lcd_wr_reg(0xE0);    //Set Gamma 
        lcd_wr_data(0x0F); 
        lcd_wr_data(0x2A); 
        lcd_wr_data(0x28); 
        lcd_wr_data(0x08); 
        lcd_wr_data(0x0E); 
        lcd_wr_data(0x08); 
        lcd_wr_data(0x54); 
        lcd_wr_data(0XA9); 
        lcd_wr_data(0x43); 
        lcd_wr_data(0x0A); 
        lcd_wr_data(0x0F); 
        lcd_wr_data(0x00); 
        lcd_wr_data(0x00); 
        lcd_wr_data(0x00); 
        lcd_wr_data(0x00); 		 
        lcd_wr_reg(0XE1);    //Set Gamma 
        lcd_wr_data(0x00); 
        lcd_wr_data(0x15); 
        lcd_wr_data(0x17); 
        lcd_wr_data(0x07); 
        lcd_wr_data(0x11); 
        lcd_wr_data(0x06); 
        lcd_wr_data(0x2B); 
        lcd_wr_data(0x56); 
        lcd_wr_data(0x3C); 
        lcd_wr_data(0x05); 
        lcd_wr_data(0x10); 
        lcd_wr_data(0x0F); 
        lcd_wr_data(0x3F); 
        lcd_wr_data(0x3F); 
        lcd_wr_data(0x0F); 
        lcd_wr_reg(0x2B); 
        lcd_wr_data(0x00);
        lcd_wr_data(0x00);
        lcd_wr_data(0x01);
        lcd_wr_data(0x3f);
        lcd_wr_reg(0x2A); 
        lcd_wr_data(0x00);
        lcd_wr_data(0x00);
        lcd_wr_data(0x00);
        lcd_wr_data(0xef);	 
        lcd_wr_reg(0x11); //Exit Sleep
        delay_ms(120);
        lcd_wr_reg(0x29); //display on	        
    }
    lcd_display_dir(0);		 	//默锟斤拷为锟斤拷锟斤拷
	LCD_LED;					//锟斤拷锟斤拷锟斤拷锟斤拷
	lcd_clear(WHITE);
}

//设置光标位置
//Xpos:横坐标
//Ypos:纵坐标
void lcd_set_cursor(uint16_t Xpos, uint16_t Ypos)
{
    lcd_wr_reg(lcddev.setxcmd);
    lcd_wr_data(Xpos>>8);
    lcd_wr_data(Xpos&0XFF);		 
    lcd_wr_reg(lcddev.setycmd);
    lcd_wr_data(Ypos>>8);
    lcd_wr_data(Ypos&0XFF);
}
//开始写GRAM
void lcd_write_GRAM_prepare(void)
{
    lcd_wr_reg(lcddev.wramcmd);
} 

//清屏函数
//color:要清屏的填充色
void lcd_clear(uint16_t color)
{
	uint32_t index=0;      
	uint32_t totalpoint=lcddev.width;
	totalpoint *= lcddev.height; 			        //得到总点数
    lcd_set_cursor(0x00,0x0000);	                //设置光标位置
	lcd_write_GRAM_prepare();     		            //开始写入GRAM	  
	for(index = 0; index < totalpoint; index++)
        lcd_wr_data(color);	
}
